package com.example.tools;

import com.example.pojo.vo.UserVo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: hualao
 * @Version: 0.0.1V
 * @Date: 2018/12/5
 * @Description: 类描述
 **/
public class JwtTools {

    private static final String KEY = "qsfafqweqwerewtetwtwt====1231314==gagagsasrqwrqwrqrw";

    /**
     * @Author: hualao
     * @Date: 2018/12/5 15:53
     * @Description: 生成token
     **/
    public static String createJwt(long ttlMillis, UserVo userVo) {
        //指定签名的时候使用的签名算法，也就是header那部分，jjwt已经将这部分内容分装好了
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        //生成JWT的时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(ttlMillis);

        //创建paload的私有声明（根据特定的业务需要添加，如果要拿这个做验证，一般是需要和jwt的接收方提前沟通好的验证方式）
        Map<String, Object> claims = new LinkedHashMap<>();
        claims.put("id", userVo.getUserId());

        //生成签名的时候使用的秘钥secret，这个方法本地封装了，一般可以从本地配置文件中读取，切记这个秘钥不能外露
        String key = KEY;

        //生成签发人
        String subject = userVo.getUsername();


        //下面就是在为payload添加各种标准声明和私有声明了
        //这里其实就是new一个JwtBuilder，设置jwt的body
        JwtBuilder builder = Jwts.builder()
                .setClaims(claims)
                //设置jti（jwt id）是JWT的唯一标示，根据业务需求，这个设置为一个不重复的值，主要用来作用为一次性的token,从而避免重放攻击
                .setId(UUID.randomUUID().toString())
                //iat：jwt签发时间
                .setIssuedAt(now)
                //代表这个JWT的主体，既它的所有人，这是一个json格式的字符串，可以存放什么userid，roldid之类的,作为用户的唯一标示
                .setSubject(subject)
                //设置签名使用的签名算法和签名使用的秘钥
                .signWith(signatureAlgorithm, key);

        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            //设置过期时间
            builder.setExpiration(exp);
        }
        return builder.compact();
    }

    /**
     * @Author: hualao
     * @Date: 2018/12/5 15:58
     * @Description: token解密
     **/
    public static Claims parseJWT(String token, UserVo userVo) {
        //签名秘钥和生成的签名的秘钥一模一样
        String key = KEY;

        //得到DefauleJwtParser
        Claims claims = Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(token).getBody();
        return claims;
    }

    /**
     * @Author: hualao
     * @Date: 2018/12/5 16:09
     * @Description: 验证token
     **/
    public static Boolean isVerify(String token, UserVo userVo) {
        //签名秘钥，和生成的签名的秘钥一模一样
        String key = KEY;

        //得到DefauleJwtParser
        Claims claims = Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(token).getBody();

        if (claims.get("id").equals(userVo.getUserId())) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
//        long ttlMillis = System.currentTimeMillis();
//        UserVo userVo = new UserVo();
//        userVo.setUserId("10000");
//        String token = createJwt(ttlMillis, userVo);
//        System.out.println(token);
//
//        Claims claims = parseJWT(token, userVo);
//        System.out.println(claims.get("id"));
//
//        userVo = new UserVo();
//        userVo.setUserId("10001");
//        boolean isVerify = isVerify(token, userVo);
//        System.out.println(isVerify);
//        System.out.println(8>>2);
//        System.out.println(2<<2);

//        System.out.println(8>>>2);

//        int a = 100;
//        for (int i = 0; i < a; i++) {
//            a = a>>2;
//            System.out.println(a);
//        }

//        8/2 = 4 = 0；
//        4/2 = 2 = 0;
//        2/2 = 1 = 0;
//        1/2 = 0 = 1;
//        1000;
//
//        10;
//        0*2^0 = 0;
//        1*2^1 = 2;

//        2/2 = 1 = 0;
//        1/2 = 0 = 1;
//
//        10;
//
//        1000;
//
//        0*2^0 = 0;
//        0*2^1 = 0;
//        0*2^2 = 0;
//        1*2^3 = 8;


//        int a = 8>>2;
//        System.out.println("8 = "+Integer.toBinaryString(8));
//        System.out.println("8 >> 2 = "+Integer.toBinaryString(a));
//        System.out.println("a = "+a);
//
//
//        int b = 2<<3;
//        System.out.println("2 = "+Integer.toBinaryString(2));
//        System.out.println("2 << 3 = "+Integer.toBinaryString(b));
//        System.out.println("b = "+b);
        String[] s = {"s","a","b","c"};
        List<String> lists = new ArrayList<>(Arrays.asList(s));

        lists.add("2");

        lists.forEach(System.out::println);
        System.out.println(lists);


        List<String> lists2 = Collections.nCopies(3,"apple");
        System.out.println(lists2);


        lists2 = Collections.nCopies(2,"test");
        System.out.println(lists2);

        List<String> lists3 = Collections.singletonList("cat");
//        lists3.add("iii");
        System.out.println(lists3);

        List<String> lists4 = Collections.emptyList();
        System.out.println(lists4);

        List<String> lists5 = new ArrayList<String>(){{
           add("2222");
        }};
        System.out.println(lists5);


        List<String> colors = Stream.of("blue","red","yellow").collect(Collectors.toList());
        System.out.println(colors);




    }
}
